home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _3D5944A7C921485FBA2CF18A5C5194E0 < prev    next >
Encoding:
Text File  |  2002-07-11  |  22.4 KB  |  1,053 lines

  1. // Copyright (C) 2001-2002 Raven Software
  2. //
  3. // g_gametype.c -- dynamic gametype handling
  4.  
  5. #include "g_local.h"
  6. #include "q_shared.h"
  7. #include "g_team.h"
  8. #include "inv.h"
  9.  
  10. #define    MAX_GAMETYPE_SPAWN_POINTS    32
  11.  
  12. void hurt_use( gentity_t *self, gentity_t *other, gentity_t *activator );
  13. void target_effect_delayed_use ( gentity_t* self );
  14.  
  15.  
  16. int            g_gametypeItemCount = 0;
  17. vec3_t        g_effectOrigin;
  18.  
  19. /*QUAKED gametype_player (0 1 0) (-16 -16 -46) (16 16 48) REDTEAM BLUETEAM
  20. Potential spawning position for red or blue team in custom gametype games.
  21. */
  22. void SP_gametype_player ( gentity_t *ent ) 
  23. {
  24.     team_t    team;
  25.  
  26.     // Cant take any more spawns!!
  27.     if ( level.spawnCount >= MAX_SPAWNS )
  28.     {
  29.         G_FreeEntity ( ent );
  30.         return;
  31.     }
  32.     
  33.     // If a team filter is set then override any team settings for the spawns
  34.     if ( level.mTeamFilter[0] )
  35.     {
  36.         if ( Q_stricmp ( level.mTeamFilter, "red") == 0 )
  37.         {
  38.             team = TEAM_RED;
  39.         }
  40.         else if ( Q_stricmp ( level.mTeamFilter, "blue") == 0 )
  41.         {
  42.             team = TEAM_BLUE;
  43.         }
  44.         else
  45.         {
  46.             G_FreeEntity ( ent );
  47.             return;
  48.         }
  49.     }
  50.     else
  51.     {
  52.         // Red team only
  53.         if ( ent->spawnflags & 0x1 )
  54.         {
  55.             team = TEAM_RED;
  56.         }
  57.         else if ( ent->spawnflags & 0x2 )
  58.         {
  59.             team = TEAM_BLUE;
  60.         }
  61.         else
  62.         {
  63.             team = TEAM_FREE;
  64.         }
  65.     }
  66.  
  67.     G_AddClientSpawn ( ent, team );
  68.  
  69.     G_FreeEntity ( ent );
  70. }
  71.  
  72. void SP_mission_player ( gentity_t* ent )
  73. {
  74.     ent->classname = "gametype_player";
  75.  
  76.     SP_gametype_player ( ent );
  77. }
  78.  
  79. void gametype_item_use ( gentity_t* self, gentity_t* other )
  80. {
  81.     if ( level.gametypeResetTime )
  82.     {
  83.         return;
  84.     }
  85.  
  86.     if ( trap_GT_SendEvent ( GTEV_ITEM_USED, level.time, self->item->quantity, other->s.number, other->client->sess.team, 0, 0 ) )
  87.     {
  88.         G_UseTargets ( self, other );
  89.     }
  90. }
  91.  
  92. void gametype_trigger_use ( gentity_t *self, gentity_t *other, gentity_t *activator ) 
  93. {
  94.     if ( level.gametypeResetTime )
  95.     {
  96.         return;
  97.     }
  98.  
  99.     if ( trap_GT_SendEvent ( GTEV_TRIGGER_USED, level.time, self->health, other->s.number, other->client->sess.team, 0, 0 ) )
  100.     {
  101.         G_UseTargets ( self, other );
  102.     }
  103. }
  104.  
  105. void gametype_trigger_touch ( gentity_t *self, gentity_t *other, trace_t *trace ) 
  106. {
  107.     if ( level.gametypeResetTime )
  108.     {
  109.         return;
  110.     }
  111.  
  112.     if ( trap_GT_SendEvent ( GTEV_TRIGGER_TOUCHED, level.time, self->health, other->s.number, other->client->sess.team, 0, 0 ) )
  113.     {
  114.         G_UseTargets ( self, other );
  115.     }
  116. }
  117.  
  118. /*QUAKED gametype_trigger (0 0 .8) ? 
  119. */
  120. void SP_gametype_trigger ( gentity_t* ent )
  121. {
  122.     // The target name is only used by the gametype system, so it shouldnt
  123.     // be adjusted by the RMG
  124.     if ( level.mTargetAdjust )
  125.     {
  126.         if ( ent->targetname )
  127.             ent->targetname = strchr ( ent->targetname, '-' ) + 1;
  128.     }
  129.  
  130.     InitTrigger (ent);
  131.  
  132.     ent->s.eType = ET_GAMETYPE_TRIGGER;
  133. }
  134.  
  135. static gentity_t* G_RealSpawnGametypeItem ( gitem_t* item, vec3_t origin, vec3_t angles, qboolean dropped )
  136. {
  137.     gentity_t* it_ent;
  138.  
  139.     it_ent = G_Spawn();
  140.  
  141.     it_ent->flags |= FL_DROPPED_ITEM;
  142.     it_ent->item = item;
  143.  
  144.     VectorCopy( origin, it_ent->s.origin );
  145.     VectorCopy ( angles, it_ent->s.apos.trBase );
  146.     VectorCopy ( angles, it_ent->s.angles );
  147.     it_ent->classname = item->classname;
  148.     G_SpawnItem ( it_ent, it_ent->item );
  149.     FinishSpawningItem(it_ent);    
  150.     
  151.     VectorSet( it_ent->r.mins, -ITEM_RADIUS * 4 / 3, -ITEM_RADIUS * 4 / 3, -ITEM_RADIUS );
  152.     VectorSet( it_ent->r.maxs, ITEM_RADIUS * 4 / 3, ITEM_RADIUS * 4 / 3, ITEM_RADIUS );
  153.  
  154.     return it_ent;
  155. }
  156.  
  157. gentity_t* G_SpawnGametypeItem ( const char* pickup_name, qboolean dropped, vec3_t origin )
  158. {
  159.     gentity_t* ent;
  160.  
  161.     if ( dropped )
  162.     {
  163.         gitem_t* item = BG_FindItem ( pickup_name );
  164.         if ( item )
  165.         {
  166.             return G_RealSpawnGametypeItem ( item, origin, vec3_origin, dropped );
  167.         }
  168.  
  169.         return NULL;
  170.     }
  171.         
  172.     // Look for the gametype item in the map
  173.     ent = NULL;
  174.     while ( NULL != (ent = G_Find ( ent, FOFS(classname), "gametype_item" ) ) )
  175.     {
  176.         // Match?
  177.         if ( !Q_stricmp ( ent->item->pickup_name, pickup_name ) )
  178.         {
  179.             break;
  180.         }
  181.     }
  182.     
  183.     // If we couldnt find the item spawner then we have a problem    
  184.     if ( !ent )
  185.     {
  186.         Com_Error ( ERR_FATAL, "Could not spawn gametype item '%s'\n", pickup_name );
  187.         return NULL;
  188.     }        
  189.  
  190.     return G_RealSpawnGametypeItem ( ent->item, ent->r.currentOrigin, ent->s.angles, dropped );
  191. }
  192.  
  193. void G_GametypeItemThink ( gentity_t* ent )
  194. {
  195.     G_RealSpawnGametypeItem ( ent->item, ent->r.currentOrigin, ent->s.angles, qfalse );
  196. }
  197.  
  198. /*QUAKED gametype_item (0 0 1) (-16 -16 -16) (16 16 16) 
  199. "name"            name of the item to spawn (defined in gametype script)
  200. */
  201. void SP_gametype_item ( gentity_t* ent )
  202. {
  203.     // TEMPORARY HACK
  204.     if ( level.mTargetAdjust )
  205.     {
  206.         if ( ent->targetname )
  207.             ent->targetname = strchr ( ent->targetname, '-' ) + 1;
  208.     
  209.         if ( ent->target )
  210.             ent->target = strchr ( ent->target, '-' ) + 1;
  211.     }
  212.  
  213.     G_SetOrigin( ent, ent->s.origin );
  214. }
  215.  
  216. /*
  217. ===============
  218. G_ResetGametypeItem
  219. ===============
  220. */
  221. void G_ResetGametypeItem ( gitem_t* item )
  222. {
  223.     gentity_t *find;
  224.     int          i;
  225.  
  226.     // Convience check
  227.     if ( !item )
  228.     {
  229.         return;
  230.     }
  231.  
  232.     // Remove all spawned instances of the item on the map
  233.     find = NULL;
  234.     while ( NULL != (find = G_Find ( find, FOFS(classname), item->classname ) ) )
  235.     {
  236.         // Free this entity soon
  237.         find->nextthink = level.time + 10;
  238.         find->think = G_FreeEntity;
  239.     }
  240.  
  241.     // Strip the item from all connected clients
  242.     for ( i = 0; i < level.numConnectedClients; i ++ )
  243.     {
  244.         g_entities[level.sortedClients[i]].client->ps.stats[STAT_GAMETYPE_ITEMS] &= ~(1<<item->giTag);
  245.     }
  246.  
  247.     // Respawn the item in all of its locations
  248.     find = NULL;
  249.     while ( NULL != (find = G_Find ( find, FOFS(classname), "gametype_item" ) ) )
  250.     {
  251.         if ( find->item != item )
  252.         {
  253.             continue;
  254.         }
  255.  
  256.         G_RealSpawnGametypeItem ( find->item, find->r.currentOrigin, find->s.angles, qfalse );
  257.     }
  258. }
  259.  
  260. /*
  261. ===============
  262. G_ResetGametypeEntities
  263. ===============
  264. */
  265. void G_ResetGametypeEntities ( void )
  266. {
  267.     gentity_t* find;
  268.     qboolean   initVisible;
  269.  
  270.     // Show total time
  271.     initVisible = qtrue;
  272.     trap_SetConfigstring ( CS_GAMETYPE_TIMER, "0" );
  273.  
  274.     // Reset all of the gametype items.  This must be done last because the spawn
  275.     // function may alter enabled states of triggers or scripts
  276.     find = NULL;
  277.     while ( NULL != (find = G_Find ( find, FOFS(classname), "gametype_item" ) ) )
  278.     {
  279.         G_ResetGametypeItem ( find->item );
  280.     }
  281. }
  282.  
  283. /*
  284. ===============
  285. G_RespawnClients
  286. ===============
  287. */
  288. void G_RespawnClients ( qboolean force, team_t team )
  289. {
  290.     int i;
  291.  
  292.     // Respawn all clients back at a spawn pointer
  293.     for ( i = 0; i < level.numConnectedClients; i ++ )
  294.     {
  295.         // Save the clients weapons
  296.         playerState_t    ps;
  297.         gentity_t*        ent;
  298.         qboolean        ghost;
  299.  
  300.         ent = &g_entities[level.sortedClients[i]];
  301.  
  302.         // Make sure they are actually connected
  303.         if ( ent->client->pers.connected != CON_CONNECTED )
  304.         {
  305.             continue;
  306.         }
  307.  
  308.         // Save the entire player state so certain things
  309.         // can be maintained across rounds
  310.         ps = ent->client->ps;
  311.  
  312.         ghost = ent->client->sess.ghost;
  313.  
  314.         // Spawn the requested team
  315.         if ( ent->client->sess.team != team )
  316.         {
  317.             continue;
  318.         }
  319.  
  320.         // Dont force them to respawn if they arent a ghost
  321.         if ( !ghost && !force )
  322.         {
  323.             continue;
  324.         }
  325.  
  326.         // If the client is a ghost then revert them
  327.         if ( ent->client->sess.ghost )
  328.         {
  329.             // Clean up any following monkey business
  330.             G_StopFollowing ( ent );
  331.  
  332.             // Disable being a ghost
  333.             ent->client->ps.pm_flags &= ~PMF_GHOST;
  334.             ent->client->ps.pm_type = PM_NORMAL;
  335.             ent->client->sess.ghost = qfalse;
  336.         }
  337.         
  338.         ent->client->sess.noTeamChange = qfalse;
  339.  
  340.         trap_UnlinkEntity (ent);
  341.         ClientSpawn ( ent );
  342.     }
  343. }
  344.  
  345. /*
  346. ===============
  347. G_ResetPickups
  348. ===============
  349. */
  350. void G_ResetEntities ( void )
  351. {
  352.     int i;
  353.  
  354.     // Run through all the entities in the level and reset those which
  355.     // need to be reset
  356.     for ( i = 0; i < level.num_entities; i ++ )
  357.     {
  358.         gentity_t* ent;
  359.  
  360.         ent = &g_entities[i];
  361.  
  362.         // Skip entities not in use
  363.         if ( !ent->inuse )
  364.         {
  365.             continue;
  366.         }
  367.  
  368.         // If this is a player then unlink it so then clients
  369.         // spawned in dont telefrag
  370.         if ( ent->s.eType == ET_PLAYER || ent->s.eType == ET_BODY )
  371.         {
  372.             trap_UnlinkEntity ( ent );
  373.         }
  374.         // If this is a missile
  375.         else if ( ent->s.eType == ET_MISSILE )
  376.         {
  377.             G_FreeEntity ( ent );
  378.         }
  379.         // func_wall's can be toggled off/on
  380.         else if ( ent->s.eType == ET_WALL )
  381.         {
  382.             if ( ent->spawnflags & 1 )
  383.             {
  384.                 trap_UnlinkEntity ( ent );
  385.             }
  386.             else
  387.             {
  388.                 trap_LinkEntity ( ent );
  389.             }
  390.         }
  391.         // If the dropped flag is set then free it
  392.         else if ( ent->flags & FL_DROPPED_ITEM )
  393.         {
  394.             G_FreeEntity ( ent );
  395.         }
  396.         // If this item is waiting to be respawned, then respawn it
  397.         else if ( ent->think == RespawnItem )
  398.         {
  399.             RespawnItem ( ent );
  400.         }
  401.         else if ( ent->s.eType == ET_DAMAGEAREA )
  402.         {
  403.             G_FreeEntity ( ent );
  404.         }
  405.         else if ( ent->use == hurt_use )
  406.         {
  407.             if ( ent->spawnflags & 1 )
  408.             {
  409.                 trap_UnlinkEntity ( ent );
  410.             }
  411.         }
  412.         else if ( ent->think == target_effect_delayed_use )
  413.         {
  414.             ent->think = 0;
  415.             ent->nextthink = 0;
  416.         }
  417.     }
  418. }
  419.  
  420. /*
  421. ===============
  422. G_ResetGametype
  423. ===============
  424. */
  425. void G_ResetGametype ( void )
  426. {
  427.     gentity_t*    tent;
  428.  
  429.     // Reset the glass in the level
  430.     G_ResetGlass ( );
  431.  
  432.     // Reset all pickups in the world
  433.     G_ResetEntities ( );
  434.  
  435.     // Reset the gametype itself
  436.     G_ResetGametypeEntities ( );
  437.  
  438.     // Initialize the respawn interval since this is a interval gametype
  439.     switch ( level.gametypeData->respawnType )
  440.     {
  441.         case RT_INTERVAL:
  442.             level.gametypeRespawnTime[TEAM_RED]  = 0;
  443.             level.gametypeRespawnTime[TEAM_BLUE] = 0;
  444.             level.gametypeRespawnTime[TEAM_FREE] = 0;
  445.             break;
  446.  
  447.         case RT_NONE:
  448.             level.gametypeDelayTime = level.time + g_roundstartdelay.integer * 1000;
  449.             level.gametypeRoundTime = level.time + (g_roundtimelimit.integer * 60000);
  450.  
  451.             if ( level.gametypeDelayTime != level.time )
  452.             {
  453.                 trap_SetConfigstring ( CS_GAMETYPE_MESSAGE, va("%i,@Get Ready", level.gametypeDelayTime ) );
  454.             }
  455.  
  456.             trap_SetConfigstring ( CS_GAMETYPE_TIMER, va("%i", level.gametypeRoundTime) );
  457.             break;
  458.     }
  459.  
  460.     level.gametypeJoinTime  = 0;
  461.  
  462.     // Allow people to join 20 seconds after both teams have people on them
  463.     if ( !level.gametypeData->teams )
  464.     {
  465.         level.gametypeJoinTime = level.time;
  466.     }
  467.  
  468.     // Respawn all clients
  469.     G_RespawnClients ( qtrue, TEAM_RED );
  470.     G_RespawnClients ( qtrue, TEAM_BLUE );
  471.  
  472.     level.gametypeStartTime = level.time;
  473.     level.gametypeResetTime = 0;
  474.  
  475.     // Reset the clients local effects
  476.     tent = G_TempEntity( vec3_origin, EV_GAMETYPE_RESTART );
  477.     tent->r.svFlags |= SVF_BROADCAST;
  478.  
  479.     // Start the gametype
  480.     trap_GT_Start ( level.gametypeStartTime );
  481. }
  482.  
  483. /*
  484. ===============
  485. G_ParseGametypeItems
  486. ===============
  487. */
  488. qboolean G_ParseGametypeItems ( TGPGroup* itemsGroup )
  489. {
  490.     TGPGroup    itemGroup;
  491.     int            itemCount;
  492.     char        temp[MAX_QPATH];
  493.     gentity_t    *ent;
  494.  
  495.     // Handle NULL for convienience
  496.     if ( !itemsGroup )
  497.     {
  498.         return qfalse;
  499.     }
  500.  
  501.     // Loop over all the items and add each 
  502.     itemGroup = trap_GPG_GetSubGroups ( itemsGroup );
  503.     itemCount = 0;
  504.  
  505.     while ( itemGroup )
  506.     {    
  507.         gitem_t*   item;
  508.         
  509.         // Parse out the pickup name
  510.         trap_GPG_GetName ( itemGroup, temp );
  511.  
  512.         item = BG_FindItem ( temp );
  513.         if ( !item )
  514.         {
  515.             item = &bg_itemlist[ MODELINDEX_GAMETYPE_ITEM + itemCount ];
  516.             item->pickup_name = (char *)trap_VM_LocalStringAlloc ( temp );
  517.             itemCount++;
  518.         }
  519.  
  520.         // Handle the entity specific stuff by finding all matching items that 
  521.         // were spawned.
  522.         ent = NULL;
  523.         while ( NULL != (ent = G_Find ( ent, FOFS(targetname), item->pickup_name ) ) )
  524.         {
  525.             // If not a gametype item then skip it
  526.             if ( Q_stricmp ( ent->classname, "gametype_item" ) )
  527.             {
  528.                 continue;
  529.             }
  530.  
  531.             // Setup the gametype data
  532.             ent->item       = item;
  533.             ent->nextthink = level.time + 200;
  534.             ent->think     = G_GametypeItemThink;
  535.         }
  536.  
  537.         // Next sub group
  538.         itemGroup = trap_GPG_GetNext(itemGroup);
  539.     }
  540.  
  541.     return qtrue;
  542. }
  543.  
  544. /*
  545. ===============
  546. G_ParseGametypeFile
  547. ===============
  548. */
  549. qboolean G_ParseGametypeFile ( void )
  550. {
  551.     TGenericParser2 GP2;
  552.     TGPGroup        topGroup;
  553.     TGPGroup        gametypeGroup;
  554.     char            value[4096];
  555.  
  556.     // Default the gametype config strings
  557.     trap_SetConfigstring ( CS_GAMETYPE_MESSAGE, "0,0" );
  558.  
  559.     // Open the given gametype file
  560.     GP2 = trap_GP_ParseFile ( (char*)level.gametypeData->script, qtrue, qfalse );
  561.     if (!GP2)
  562.     {
  563.         return qfalse;
  564.     }
  565.  
  566.     // Grab the top group and the list of sub groups
  567.     topGroup = trap_GP_GetBaseParseGroup(GP2);
  568.     gametypeGroup = trap_GPG_FindSubGroup(topGroup, "gametype" );
  569.     if ( !gametypeGroup )
  570.     {
  571.         trap_GP_Delete(&GP2);
  572.         return qfalse;
  573.     }
  574.  
  575.     // Look for the respawn type
  576.     trap_GPG_FindPairValue ( gametypeGroup, "respawn", "normal", value );
  577.     if ( !Q_stricmp ( value, "none" ) )
  578.     {
  579.         level.gametypeData->respawnType = RT_NONE;
  580.     }
  581.     else if ( !Q_stricmp ( value, "interval" ) )
  582.     {
  583.         level.gametypeData->respawnType = RT_INTERVAL;
  584.     }
  585.     else
  586.     {
  587.         level.gametypeData->respawnType = RT_NORMAL;
  588.     }
  589.  
  590.     // Grab the defined items
  591.     G_ParseGametypeItems ( trap_GPG_FindSubGroup ( gametypeGroup, "items" ) );
  592.  
  593.     // Free up the parser
  594.     trap_GP_Delete(&GP2);
  595.  
  596.     return qtrue;
  597. }
  598.  
  599. /*
  600. =================
  601. G_EnableGametypeItemPickup
  602.  
  603. Drops all of the gametype items held by the player
  604. =================
  605. */
  606. void G_EnableGametypeItemPickup ( gentity_t* ent )
  607. {
  608.     ent->s.eFlags &= ~EF_NOPICKUP;
  609. }
  610.  
  611. /*
  612. =================
  613. G_DropGametypeItems
  614.  
  615. Drops all of the gametype items held by the player
  616. =================
  617. */
  618. void G_DropGametypeItems ( gentity_t* self )
  619. {
  620.     float        angle;
  621.     int            i;
  622.     gentity_t    *drop;
  623.     gitem_t        *item;
  624.  
  625.     // drop all custom gametype items
  626.     angle = 0;
  627.     for ( i = 0 ; i < MAX_GAMETYPE_ITEMS ; i++ ) 
  628.     {
  629.         // skip this gametype item if the client doenst have it
  630.         if ( !(self->client->ps.stats[STAT_GAMETYPE_ITEMS] & (1<<i)) ) 
  631.         {
  632.             continue;
  633.         }
  634.  
  635.         item = BG_FindGametypeItem ( i );
  636.         if ( !item ) 
  637.         {
  638.             continue;
  639.         }
  640.  
  641.         drop = G_DropItem( self, item, angle );
  642.         drop->count = 1;
  643.         angle += 45;
  644.  
  645.         drop->nextthink = level.time + 3000;    
  646.         drop->s.eFlags |= EF_NOPICKUP;
  647.         drop->think = G_EnableGametypeItemPickup;
  648.         
  649.         // TAke it away from the client just in case
  650.         self->client->ps.stats[STAT_GAMETYPE_ITEMS] &= ~(1<<i);
  651.  
  652.         if ( self->enemy && self->enemy->client && !OnSameTeam ( self->enemy, self ) )
  653.         {
  654.             trap_GT_SendEvent ( GTEV_ITEM_DEFEND, level.time, level.gametypeItems[item->giTag].id, self->enemy->s.clientNum, self->enemy->client->sess.team, 0, 0  );
  655.         }
  656.     }
  657.  
  658.     self->client->ps.stats[STAT_GAMETYPE_ITEMS] = 0;
  659. }
  660.  
  661. /*
  662. =================
  663. CheckGametype
  664. =================
  665. */
  666. void CheckGametype ( void )
  667. {
  668.     // If the level is over then forget checking gametype stuff.
  669.     if ( level.intermissiontime )
  670.     {
  671.         return;
  672.     }
  673.  
  674.     // Dont bother starting the gametype until
  675.     // the first person joins
  676.     if ( !level.gametypeStartTime )
  677.     {
  678.         int counts[TEAM_NUM_TEAMS];
  679.         int i;
  680.  
  681.         memset ( counts, 0, sizeof(counts) );
  682.  
  683.         for ( i = 0; i < level.numConnectedClients; i ++ )
  684.         {
  685.             gentity_t* other = &g_entities[level.sortedClients[i]];
  686.  
  687.             if ( other->client->pers.connected != CON_CONNECTED )
  688.             {
  689.                 continue;
  690.             }
  691.                 
  692.             if ( other->client->pers.connected != CON_CONNECTED )
  693.             {
  694.                 continue;
  695.             }
  696.  
  697.             counts[other->client->sess.team]++;
  698.         }
  699.  
  700.         if ( counts[TEAM_RED] || counts[TEAM_BLUE] )
  701.         {
  702.             G_ResetGametype ( );
  703.             return;
  704.         }
  705.     }
  706.  
  707.     // Check for delayed gametype reset
  708.     if ( level.gametypeResetTime )
  709.     {
  710.         if ( level.time > level.gametypeResetTime )
  711.         {
  712.             // Dont do this again
  713.             level.gametypeResetTime = 0;
  714.  
  715.             G_ResetGametype ( );
  716.         }
  717.  
  718.         return;
  719.     }
  720.  
  721.     // Handle respawn interval spawning
  722.     if ( level.gametypeData->respawnType == RT_INTERVAL )
  723.     {
  724.         team_t team;
  725.         for ( team = TEAM_RED; team < TEAM_SPECTATOR; team ++ )
  726.         {
  727.             if ( level.gametypeRespawnTime[team] && level.time > level.gametypeRespawnTime[team] )
  728.             {
  729.                 // Respawn all dead clients
  730.                 G_RespawnClients ( qfalse, team );
  731.  
  732.                 // Next interval
  733.                 level.gametypeRespawnTime[team] = 0;
  734.             }
  735.         }
  736.     }
  737.  
  738.     // If we are in RT_NONE respawn mode then we need to look for everyone being dead
  739.     if ( level.time > level.gametypeDelayTime && level.gametypeData->respawnType == RT_NONE && level.gametypeStartTime )
  740.     {
  741.         int i;
  742.         int alive[TEAM_NUM_TEAMS];
  743.         int dead[TEAM_NUM_TEAMS];
  744.  
  745.         memset ( &alive[0], 0, sizeof(alive) );
  746.         memset ( &dead[0], 0, sizeof(dead) );
  747.         for ( i = 0; i < level.numConnectedClients; i ++ )
  748.         {
  749.             gentity_t* ent = &g_entities[level.sortedClients[i]];
  750.  
  751.             if ( ent->client->pers.connected != CON_CONNECTED )
  752.             {
  753.                 continue;
  754.             }
  755.  
  756.             if ( G_IsClientDead ( ent->client ) )
  757.             {
  758.                 dead[ent->client->sess.team] ++;
  759.             }
  760.             else
  761.             {
  762.                 alive[ent->client->sess.team] ++;
  763.             }
  764.         }
  765.  
  766.         // If everyone is dead on a team then reset the gametype, but only if 
  767.         // there was someone on that team to begin with.
  768.         if ( !alive[TEAM_RED] && dead[TEAM_RED] )
  769.         {            
  770.             trap_GT_SendEvent ( GTEV_TEAM_ELIMINATED, level.time, TEAM_RED, 0, 0, 0, 0 );
  771.         }
  772.         else if ( !alive[TEAM_BLUE] && dead[TEAM_BLUE] )
  773.         {            
  774.             trap_GT_SendEvent ( GTEV_TEAM_ELIMINATED, level.time, TEAM_BLUE, 0, 0, 0, 0 );
  775.         }
  776.  
  777.         // See if the time has expired
  778.         if ( level.time > level.gametypeRoundTime )
  779.         {
  780.             trap_GT_SendEvent ( GTEV_TIME_EXPIRED, level.time, 0, 0, 0, 0, 0 );
  781.         } 
  782.     }
  783. }
  784.  
  785. /*
  786. =================
  787. G_GametypeCommand
  788.  
  789. Handles a command coming from the current gametype VM
  790. =================
  791. */
  792. int G_GametypeCommand ( int cmd, int arg0, int arg1, int arg2, int arg3, int arg4 )
  793. {
  794.     switch ( cmd )
  795.     {
  796.         case GTCMD_RESTART:
  797.             if ( arg0 <= 0 )
  798.             {
  799.                 G_ResetGametype ( );
  800.             }
  801.             else
  802.             {
  803.                 level.gametypeResetTime = level.time + arg0 * 1000;
  804.             }
  805.             break;
  806.  
  807.         case GTCMD_TEXTMESSAGE:
  808.             trap_SetConfigstring ( CS_GAMETYPE_MESSAGE, va("%i,%s", level.time + 5000, (const char*)arg1 ) );
  809.             break;        
  810.  
  811.         case GTCMD_RADIOMESSAGE:
  812.             G_Voice ( &g_entities[arg0], NULL, SAY_TEAM, (const char*) arg1, qfalse );
  813.             break;
  814.  
  815.         case GTCMD_REGISTERSOUND:
  816.             return G_SoundIndex ( (char*) arg0 );
  817.  
  818.         case GTCMD_STARTGLOBALSOUND:
  819.         {
  820.             gentity_t* tent;
  821.             tent = G_TempEntity( vec3_origin, EV_GLOBAL_SOUND );
  822.             tent->s.eventParm = arg0;
  823.             tent->r.svFlags = SVF_BROADCAST;    
  824.             break;
  825.         }    
  826.  
  827.         case GTCMD_STARTSOUND:
  828.             G_SoundAtLoc ( (float*)arg1, CHAN_AUTO, arg0 );
  829.             break;
  830.  
  831.         case GTCMD_REGISTEREFFECT:
  832.             return G_EffectIndex ( (char*) arg0 );
  833.  
  834.         case GTCMD_REGISTERICON:
  835.             return G_IconIndex ( (char*) arg0 );
  836.  
  837.         case GTCMD_SETHUDICON:
  838.             G_SetHUDIcon ( arg0, arg1 );
  839.             break;
  840.  
  841.         case GTCMD_PLAYEFFECT:
  842.             G_PlayEffect ( arg0, (float*) arg1, (float*) arg2 );
  843.             break;
  844.  
  845.         case GTCMD_ADDCLIENTSCORE:
  846.             G_AddScore ( &g_entities[arg0], arg1 );
  847.             break;
  848.  
  849.         case GTCMD_ADDTEAMSCORE:
  850.             G_AddTeamScore ( (team_t) arg0, arg1 );
  851.             break;
  852.  
  853.         case GTCMD_RESETITEM:
  854.         {
  855.             gitem_t* item;
  856.  
  857.             item = BG_FindGametypeItemByID ( arg0 );
  858.             if ( item )
  859.             {
  860.                 G_ResetGametypeItem ( item );
  861.                 return qtrue;
  862.             }
  863.             break;
  864.         }
  865.  
  866.         case GTCMD_GETCLIENTNAME:
  867.             Com_sprintf ( (char*) arg1, arg2, "%s", g_entities[arg0].client->pers.netname );
  868.             break;
  869.  
  870.         case GTCMD_GETTRIGGERTARGET:
  871.         {
  872.             gentity_t    *find;
  873.  
  874.             Com_sprintf ( (char*) arg1, arg2, "" );
  875.  
  876.             find = NULL;
  877.             while ( NULL != (find = G_Find ( find, FOFS(classname), "gametype_trigger" ) ) )
  878.             {
  879.                 if ( find->health == arg0 )
  880.                 {
  881.                     Com_sprintf ( (char*) arg1, arg2, "%s", find->target );
  882.                     break;
  883.                 }
  884.             }
  885.  
  886.             break;
  887.         }
  888.  
  889.         case GTCMD_GETCLIENTORIGIN:
  890.             VectorCopy ( g_entities[arg0].client->ps.origin, (float*) arg1 );
  891.             break;
  892.  
  893.         case GTCMD_GIVECLIENTITEM:
  894.         {
  895.             gitem_t* item;
  896.             
  897.             item = BG_FindGametypeItemByID ( arg1 );
  898.             if ( item )
  899.             {
  900.                 level.clients[arg0].ps.stats[STAT_GAMETYPE_ITEMS] |= (1<<item->giTag);
  901.             }
  902.             break;
  903.         }
  904.  
  905.         case GTCMD_GETCLIENTLIST:
  906.         {
  907.             int  i;
  908.             int  count;
  909.             int *clients = (int*)arg1;
  910.  
  911.             for ( i = 0, count = 0; i < level.numConnectedClients && count < arg2; i ++ )
  912.             {
  913.                 gclient_t* client = &level.clients[level.sortedClients[i]];
  914.                 
  915.                 if ( client->pers.connected != CON_CONNECTED )
  916.                 {
  917.                     continue;
  918.                 }
  919.  
  920.                 if ( client->sess.team == arg0 )
  921.                 {
  922.                     *clients = level.sortedClients[i];
  923.                     clients++;
  924.                     count++;
  925.                 }                
  926.             }
  927.  
  928.             return count;
  929.         }
  930.  
  931.         case GTCMD_TAKECLIENTITEM:
  932.         {
  933.             gitem_t* item;
  934.             
  935.             item = BG_FindGametypeItemByID ( arg1 );
  936.             if ( item )
  937.             {
  938.                 level.clients[arg0].ps.stats[STAT_GAMETYPE_ITEMS] &= ~(1<<item->giTag);
  939.             }
  940.             break;
  941.         }            
  942.  
  943.         case GTCMD_SPAWNITEM:
  944.         {
  945.             gitem_t* item;
  946.             
  947.             item = BG_FindGametypeItemByID ( arg0 );
  948.             if ( item )
  949.             {
  950.                 gentity_t* ent = LaunchItem ( item, (float*)arg1, vec3_origin );
  951.                 if ( ent ) 
  952.                 {
  953.                     VectorCopy ( (float*)arg2, ent->s.angles );
  954.                 }
  955.             }
  956.             break;
  957.         }            
  958.  
  959.         case GTCMD_DOESCLIENTHAVEITEM:
  960.         {
  961.             gitem_t*    item;
  962.             gentity_t*    ent;
  963.  
  964.             ent  = &g_entities[arg0];
  965.             item = BG_FindGametypeItemByID ( arg1 );
  966.  
  967.             if ( item )
  968.             {
  969.                 if ( ent->client->ps.stats[STAT_GAMETYPE_ITEMS] & (1<<item->giTag) )
  970.                 {
  971.                     return 1;
  972.                 }
  973.             }
  974.  
  975.             return 0;
  976.         }
  977.  
  978.         case GTCMD_REGISTERITEM:
  979.         {
  980.             gitem_t        *item;
  981.             gtItemDef_t    *def;
  982.  
  983.             def = (gtItemDef_t*)arg2;
  984.  
  985.             item = BG_FindItem ( (const char*) arg1 );
  986.             if ( item )
  987.             {
  988.                 gtitem_t *gtitem;
  989.  
  990.                 gtitem = &level.gametypeItems[item->giTag];
  991.  
  992.                 gtitem->id = arg0;
  993.                 item->quantity = arg0;
  994.  
  995.                 // See if the trigger needs to be used.
  996.                 if ( def && def->size == sizeof(gtItemDef_t) && def->use )
  997.                 {
  998.                     gtitem->useIcon  = def->useIcon;
  999.                     gtitem->useTime  = def->useTime;
  1000.                     gtitem->useSound = def->useSound;
  1001.                 }
  1002.  
  1003.                 return qtrue;
  1004.             }
  1005.  
  1006.             return qfalse;
  1007.         }
  1008.  
  1009.         case GTCMD_REGISTERTRIGGER:
  1010.         {
  1011.             gentity_t        *find;
  1012.             gtTriggerDef_t    *def;
  1013.  
  1014.             def = (gtTriggerDef_t*)arg2;
  1015.  
  1016.             find = NULL;
  1017.             while ( NULL != (find = G_Find ( find, FOFS(classname), "gametype_trigger" ) ) )
  1018.             {
  1019.                 if ( Q_stricmp ( find->targetname, (const char*) arg1 ) )
  1020.                 {
  1021.                     continue;
  1022.                 }
  1023.  
  1024.                 // Assign the id to it.
  1025.                 find->health = arg0;
  1026.                 find->touch  = gametype_trigger_touch;
  1027.  
  1028.                 // See if the trigger needs to be used.
  1029.                 if ( def && def->size == sizeof(gtTriggerDef_t) && def->use )
  1030.                 {
  1031.                     find->use        = gametype_trigger_use;
  1032.                     find->delay        = def->useIcon;
  1033.                     find->soundPos1 = def->useTime;
  1034.                     find->soundLoop = def->useSound;
  1035.                 }
  1036.  
  1037.                 trap_LinkEntity (find);
  1038.             }
  1039.  
  1040.             return 0;
  1041.         }
  1042.  
  1043.         case GTCMD_USETARGETS:
  1044.             G_UseTargetsByName ( (const char*) arg0, NULL, NULL );
  1045.             break;
  1046.  
  1047.         default:
  1048.             break;
  1049.     }
  1050.  
  1051.     return -1;
  1052. }
  1053.